// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//
#pragma once

#include <memory>
#include <shared_mutex>
#include <turbo/container/flat_hash_map.h>
#include <turbo/utility/status.h>

namespace cantor {
    class Type;
    using TypePtr = std::shared_ptr<const Type>;

    /////////////////////////////////////////////////////////////////////////////
    /// NOTE: we do not lock it. design it just a tool kit
    /// during multi thread,you need to choice the
    /// th lock policy your self
    /// type uri: ns.db.table.type
    ///           ns.db.type
    ///           ns.type
    ///           type
    ///
    /// NOTE: all the name we will turn to lower case.
    ///
    /// if we will try the `type` in ns, ns.db, ns.db.table scopes.
    /// if the policy root_first is true, we will try it first in
    /// lower scope first.
    /////////////////////////////////////////////////////////////////////////////

    class TypeRegistry {
    public:
        TypeRegistry() = default;

        ~TypeRegistry() = default;

        turbo::Status register_type(std::string_view uri, const TypePtr &type);

        turbo::Status remove_type(std::string_view uri, bool not_found_as_ok = false);

        turbo::Result<TypePtr> resolve_type(std::string_view uri, bool root_first = false) const;

        size_t size() const {
            return _type_map.size();
        }

        const turbo::flat_hash_map<std::string, TypePtr> &type_map() const {
            return _type_map;
        }

    private:
        turbo::Result<TypePtr> resolve_fragment_root_first(const std::vector<std::string_view> &uris,
                                                           std::string_view type_str,
                                                           std::string_view full_query) const;

        turbo::Result<TypePtr> resolve_fragment_root_last(const std::vector<std::string_view> &uri,
                                                          std::string_view type_str, std::string_view full_query) const;

        turbo::flat_hash_map<std::string, TypePtr> _type_map;
    };
} // namespace cantor
